/**
 * Mock 推理引擎
 * 
 * 功能：
 * 1. 分析源代码，判断哪些依赖需要 Mock
 * 2. 提供 Mock 使用建议和示例
 * 3. 基于工程实践学习的 Mock 模式
 */

import * as path from 'path';
import * as fs from 'fs';
import { Logger } from '../../../src/logger/Logger';

interface MockRecommendation {
    shouldMock: boolean;
    reason: string;
    mockType: 'systemAbility' | 'ipc' | 'fileIO' | 'database' | 'externalService' | 'none';
    mockExamples?: string[];
    mockFiles?: string[];
}

interface MockPattern {
    testFile: string;
    mockFile: string;
    mockClasses: string[];
}

interface MockUsagePatterns {
    externalServiceMock: MockPattern[];
    systemAbilityMock: MockPattern[];
    ipcMock: MockPattern[];
    fileIOMock: MockPattern[];
    databaseMock: MockPattern[];
}

export class MockInferenceEngine {
    private static mockKnowledge: MockUsagePatterns | null = null;
    private static testToMockMapping: Record<string, any[]> | null = null;

    /**
     * 加载 Mock 知识库（懒加载）
     */
    private static loadMockKnowledge(): void {
        if (this.mockKnowledge !== null) {
            return;
        }

        try {
            // 尝试加载 Foundation 学习数据
            const foundationIndexPath = path.join(__dirname, '../../../core/knowledge/foundation-deep-index.json');
            if (fs.existsSync(foundationIndexPath)) {
                const index = JSON.parse(fs.readFileSync(foundationIndexPath, 'utf-8'));
                
                // 加载 Mock 使用模式
                if (index.mockUsagePatternsFile) {
                    const mockPatternsPath = path.join(__dirname, '../../../core/knowledge', index.mockUsagePatternsFile);
                    if (fs.existsSync(mockPatternsPath)) {
                        this.mockKnowledge = JSON.parse(fs.readFileSync(mockPatternsPath, 'utf-8'));
                        Logger.info('[MockInferenceEngine] ✅ 加载 Foundation Mock 模式');
                    }
                }

                // 加载 Test → Mock 映射
                if (index.testToMockMappingFile) {
                    const mappingPath = path.join(__dirname, '../../../core/knowledge', index.testToMockMappingFile);
                    if (fs.existsSync(mappingPath)) {
                        this.testToMockMapping = JSON.parse(fs.readFileSync(mappingPath, 'utf-8'));
                        Logger.info('[MockInferenceEngine] ✅ 加载 Test-Mock 映射');
                    }
                }
            }

            if (!this.mockKnowledge) {
                Logger.warn('[MockInferenceEngine] ⚠️ 未找到 Mock 知识库，使用默认规则');
                this.mockKnowledge = {
                    externalServiceMock: [],
                    systemAbilityMock: [],
                    ipcMock: [],
                    fileIOMock: [],
                    databaseMock: []
                };
            }
        } catch (error) {
            Logger.error('[MockInferenceEngine] ❌ 加载 Mock 知识库失败: ' + (error instanceof Error ? error.message : String(error)));
            this.mockKnowledge = {
                externalServiceMock: [],
                systemAbilityMock: [],
                ipcMock: [],
                fileIOMock: [],
                databaseMock: []
            };
        }
    }

    /**
     * 分析源代码，推断是否需要 Mock
     * 
     * @param sourceCode 源代码
     * @param dependencies 已解析的依赖（头文件）
     * @returns Mock 推荐
     */
    public static analyzeMockNecessity(
        sourceCode: string,
        dependencies: string[] = []
    ): MockRecommendation {
        this.loadMockKnowledge();

        const lowerCode = sourceCode.toLowerCase();
        const allDeps = dependencies.join(' ').toLowerCase();

        // === 规则1: SystemAbility（系统能力）===
        if (this.hasSystemAbility(lowerCode, allDeps)) {
            return {
                shouldMock: true,
                reason: '检测到 SystemAbility 调用，需要 Mock 系统服务',
                mockType: 'systemAbility',
                mockExamples: this.getMockExamples('systemAbilityMock'),
                mockFiles: this.findRelevantMockFiles('systemAbilityMock')
            };
        }

        // === 规则2: IPC/Binder 调用 ===
        if (this.hasIPCCall(lowerCode, allDeps)) {
            return {
                shouldMock: true,
                reason: '检测到 IPC/Binder 跨进程调用，需要 Mock IPC 通信',
                mockType: 'ipc',
                mockExamples: this.getMockExamples('ipcMock'),
                mockFiles: this.findRelevantMockFiles('ipcMock')
            };
        }

        // === 规则3: 文件 I/O 操作 ===
        if (this.hasFileIO(lowerCode, allDeps)) {
            return {
                shouldMock: true,
                reason: '检测到文件 I/O 操作，建议 Mock 文件系统',
                mockType: 'fileIO',
                mockExamples: this.getMockExamples('fileIOMock'),
                mockFiles: this.findRelevantMockFiles('fileIOMock')
            };
        }

        // === 规则4: 数据库操作 ===
        if (this.hasDatabase(lowerCode, allDeps)) {
            return {
                shouldMock: true,
                reason: '检测到数据库操作，建议 Mock 数据库接口',
                mockType: 'database',
                mockExamples: this.getMockExamples('databaseMock'),
                mockFiles: this.findRelevantMockFiles('databaseMock')
            };
        }

        // === 规则5: 外部服务调用 ===
        if (this.hasExternalService(lowerCode, allDeps)) {
            return {
                shouldMock: true,
                reason: '检测到外部服务调用，建议 Mock 外部依赖',
                mockType: 'externalService',
                mockExamples: this.getMockExamples('externalServiceMock'),
                mockFiles: this.findRelevantMockFiles('externalServiceMock')
            };
        }

        // === 默认：纯逻辑代码，无需 Mock ===
        return {
            shouldMock: false,
            reason: '纯逻辑代码，无外部依赖，无需 Mock',
            mockType: 'none'
        };
    }

    /**
     * 检测是否包含 SystemAbility 调用
     */
    private static hasSystemAbility(code: string, deps: string): boolean {
        const patterns = [
            /systemability/i,
            /samgr/i,
            /getabilitymanager/i,
            /abilitymanagerservice/i,
            /systemabilitymanager/i
        ];
        return patterns.some(p => p.test(code) || p.test(deps));
    }

    /**
     * 检测是否包含 IPC/Binder 调用
     */
    private static hasIPCCall(code: string, deps: string): boolean {
        const patterns = [
            /\bipc\b/i,
            /binder/i,
            /iremoteobject/i,
            /iremoteproxy/i,
            /messageparcel/i,
            /messageoption/i
        ];
        return patterns.some(p => p.test(code) || p.test(deps));
    }

    /**
     * 检测是否包含文件 I/O 操作
     */
    private static hasFileIO(code: string, deps: string): boolean {
        const patterns = [
            /\bfopen\b/i,
            /\bfwrite\b/i,
            /\bfread\b/i,
            /filemanager/i,
            /storage/i,
            /\bopen\(/i,
            /\bread\(/i,
            /\bwrite\(/i
        ];
        return patterns.some(p => p.test(code));
    }

    /**
     * 检测是否包含数据库操作
     */
    private static hasDatabase(code: string, deps: string): boolean {
        const patterns = [
            /database/i,
            /\bsql\b/i,
            /\brdb\b/i,
            /relationalstore/i,
            /kvstore/i
        ];
        return patterns.some(p => p.test(code) || p.test(deps));
    }

    /**
     * 检测是否包含外部服务调用
     */
    private static hasExternalService(code: string, deps: string): boolean {
        const patterns = [
            /client/i,
            /proxy/i,
            /service/i,
            /manager/i
        ];
        // 必须同时包含"调用"关键字
        const hasCall = /->|\.get|\.call|\.send|\.request/i.test(code);
        return hasCall && patterns.some(p => p.test(code));
    }

    /**
     * 获取相关的 Mock 示例
     */
    private static getMockExamples(mockType: keyof MockUsagePatterns): string[] {
        if (!this.mockKnowledge || !this.mockKnowledge[mockType]) {
            return [];
        }

        const patterns = this.mockKnowledge[mockType];
        return patterns.slice(0, 3).map(p => {
            const classes = p.mockClasses && p.mockClasses.length > 0 
                ? p.mockClasses.join(', ') 
                : path.basename(p.mockFile);
            return `Mock示例: ${classes}`;
        });
    }

    /**
     * 查找相关的 Mock 文件路径
     */
    private static findRelevantMockFiles(mockType: keyof MockUsagePatterns): string[] {
        if (!this.mockKnowledge || !this.mockKnowledge[mockType]) {
            return [];
        }

        const patterns = this.mockKnowledge[mockType];
        return patterns.slice(0, 5).map(p => p.mockFile);
    }

    /**
     * 格式化 Mock 建议为 Prompt
     */
    public static formatMockRecommendationForPrompt(recommendation: MockRecommendation): string {
        if (!recommendation.shouldMock) {
            return `\n**Mock 建议**: 此代码为纯逻辑，无需使用 Mock。\n`;
        }

        let prompt = `\n**Mock 建议** (⚠️ 重要):\n`;
        prompt += `- **是否需要 Mock**: ✅ 是\n`;
        prompt += `- **原因**: ${recommendation.reason}\n`;
        prompt += `- **Mock 类型**: ${recommendation.mockType}\n`;

        if (recommendation.mockExamples && recommendation.mockExamples.length > 0) {
            prompt += `- **参考示例**:\n`;
            for (const example of recommendation.mockExamples) {
                prompt += `  - ${example}\n`;
            }
        }

        if (recommendation.mockFiles && recommendation.mockFiles.length > 0) {
            prompt += `- **相关 Mock 文件** (供参考):\n`;
            for (const file of recommendation.mockFiles.slice(0, 3)) {
                prompt += `  - \`${file}\`\n`;
            }
        }

        prompt += `\n**Mock 使用指南**:\n`;
        prompt += `1. 在 SetUp() 中初始化 Mock 对象\n`;
        prompt += `2. 使用 EXPECT_CALL 设置预期行为\n`;
        prompt += `3. 在 TearDown() 中清理 Mock 对象\n`;
        prompt += `4. Mock 应该只针对外部依赖，不要 Mock 被测函数本身\n\n`;

        return prompt;
    }
}

